<?php
/**
 * jishupu-cms
 * @Author:技术铺
 * @Date:2021/11/22
 */

namespace App\Services;

use App\Models\InfoCategory;
use App\Models\Permission;
use App\Models\User;
use App\Models\UserRole;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;

/**
 * 权限验证服务层
 * 功能：获取权限、菜单权限验证、栏目权限验证等
 *
 * Class PermissionService
 * @package App\Services
 */
class PermissionService
{

    /**
     * 获取系统权限缓存标识
     * @return string
     */
    public static function getSysPermissionCacheId()
    {
        return "sysPermissionCache";
    }

    /**
     * 获取系统通用权限缓存标识
     * @return string
     */
    public static function getSysPublicPermissionCacheId()
    {
        return "sysPublicPermissionCache";
    }

    /**
     * 获取登录管理员权限缓存标识
     * @param int $userId
     * @return string
     */
    public static function getLoginUserPermissionCacheId($userId = 0)
    {
        $userId = $userId > 0 ? $userId : Auth::id();
        return "loginUser" . $userId . "PermissionCache";
    }

    /**
     * 获取栏目权限标识
     * @param int $category_id 栏目标识
     * @return string
     */
    public static function getCategoryPermissionName($category_id = 0)
    {
        return "admin.infoCategoryData" . $category_id;
    }

    /**
     * 获取所有所属模块列表
     * @return mixed
     */
    public static function getAllController()
    {
        return Permission::where('type', 1)->pluck('controller')->toArray();
    }

    /**
     * 获取所有权限列表
     * @return mixed
     */
    public static function getAllPriv()
    {
        return Permission::where('type', 2)->pluck('priv')->toArray();
    }

    /**
     * 获取登录管理员拥有的权限集
     * @param int $userId
     * @return array|mixed|null
     */
    public static function getLoginUserPermission($userId = 0)
    {
        $get_user = Auth::user();
        if ($userId > 0) {
            $get_user = User::where('id', $userId)->first();
            if (!$get_user) return false;
        } else {
            $userId = $get_user ? $get_user->id : 0;
        }
        $user_permission_cache_id = self::getLoginUserPermissionCacheId($userId);
        $userPermissionCache = CacheService::getTagsCache(['loginUser', 'permission'], $user_permission_cache_id);
        if ($userPermissionCache == null) {
            $get_user_role = UserRole::where('user_id', $userId)->get();
            $menu_permission = [];
            $cate_permission = [];
            if ($get_user->sys) {
                $menu_permission = ['admin'];
                $cate_permission = ['admin'];
                $login_permission = ['admin'];
            } else {
                if ($get_user_role->first()) {
                    collect($get_user_role)->each(function ($item) use (&$menu_permission, &$cate_permission) {
                        /**
                         * 菜单权限
                         */
                        collect($item->roleMenuPermission)->each(function ($role_menu_permission) use (&$menu_permission) {
                            if (!empty($role_menu_permission->permission->priv) && !in_array($role_menu_permission->permission->priv, $menu_permission)) {
                                $menu_permission[] = $role_menu_permission->permission->priv;
                            }
                        });
                        /**
                         * 栏目权限
                         * admin.permission.infoCategoryData\d
                         */
                        collect($item->roleCategory)->each(function ($role_category) use (&$cate_permission) {
                            if (isset($role_category->infoCategory) && !in_array($role_category->infoCategory->id, $cate_permission)) {
                                $id = self::getCategoryPermissionName($role_category->infoCategory->id);
                                $cate_permission[] = $id;
                            }
                        });
                    });
                }
                /**
                 * 登录后通用权限
                 */
                $login_permission = self::getAllLoginPermission();
            }
            $permissionMerge = array_unique(array_merge($menu_permission, $cate_permission, $login_permission));
            $userPermissionCache = [
                'all' => $permissionMerge,
                'menu' => $menu_permission,
                'cate' => $cate_permission,
                'login' => $login_permission
            ];
            CacheService::setTagsCache(['loginUser', 'permission'], $user_permission_cache_id, $userPermissionCache);
        }
        return $userPermissionCache;
    }

    /**
     * 获取登录管理员菜单权限
     * @return array
     */
    public static function getLoginUserMenuPermission()
    {
        $getLoginUserPermission = self::getLoginUserPermission();
        return $getLoginUserPermission && isset($getLoginUserPermission['menu']) ? $getLoginUserPermission['menu'] : [];
    }

    /**
     * 获取登录管理员栏目权限
     * @return array
     */
    public static function getLoginUserCategoryPermission()
    {
        $getLoginUserPermission = self::getLoginUserPermission();
        return $getLoginUserPermission && isset($getLoginUserPermission['cate']) ? $getLoginUserPermission['cate'] : [];
    }


    /**
     * 获取系统所有（菜单、栏目）的权限
     * @return array
     */
    public static function getAllSysPermission()
    {
        $systemPermissionCache = CacheService::getCache(self::getSysPermissionCacheId());
        if ($systemPermissionCache == null) {
            $menuPermission = []; // 菜单需要的所有权限
            $loginPermission = []; // 登录后通用
            $modulePermission = []; // 模块内通用
            collect(Permission::all())->filter(function ($value, $key) use (&$menuPermission, &$loginPermission, &$modulePermission) {
                if ($value['public_type'] == 1 && !empty($value['priv'])) {
                    $loginPermission[] = $value['priv'];
                } else if ($value['public_type'] == 2 && !empty($value['priv'])) {
                    $modulePermission[] = $value['priv'];
                }
                if (!empty($value['priv'])) {
                    $menuPermission[] = $value['priv'];
                }
            });

            // 栏目权限
            $catePermission = [];
            collect(InfoCategory::pluck('id'))->each(function ($category_id) use (&$catePermission) {
                array_push($catePermission, self::getCategoryPermissionName($category_id));
            });

            $permissionMerge = array_merge($menuPermission, $catePermission);
            $systemPermissionCache = [
                'all' => $permissionMerge,
                'menu' => $menuPermission,
                'cate' => $catePermission,
                'module' => $modulePermission,
                'login' => $loginPermission
            ];
            CacheService::setCache(self::getSysPermissionCacheId(), $systemPermissionCache);
        }
        return $systemPermissionCache;
    }

    /**
     * 获取所有系统通用（登录后通用、模块通用、公共）权限
     */
    public static function getAllSystemPublicPermission()
    {
        $getSysPublicPermissionCache = CacheService::getCache(self::getSysPublicPermissionCacheId());
        if ($getSysPublicPermissionCache == null) {
            $publicPermission = Permission::where('public_type', '>', 0)->select('public_type', 'priv')->get();
            $loginPublic = [];
            $modulePublic = [];
            $public = [];
            collect($publicPermission)->each(function ($item) use (&$loginPublic, &$modulePublic, &$public) {
                if ($item->public_type == 1) $loginPublic[] = $item->priv;
                else if ($item->public_type == 2) $modulePublic[] = $item->priv;
                else $public[] = $item->priv;
            });
            $getSysPublicPermissionCache = [
                'login' => $loginPublic,
                'module' => $modulePublic,
                'public' => $public
            ];
            CacheService::setCache(self::getSysPublicPermissionCacheId(), $getSysPublicPermissionCache);
        }
        return $getSysPublicPermissionCache;
    }

    /**
     * 获取所有菜单权限
     * @return array
     */
    public static function getAllMenuPermission()
    {
        $getAllSysPermission = self::getAllSysPermission();
        return $getAllSysPermission && isset($getAllSysPermission['menu']) ? $getAllSysPermission['menu'] : [];
    }

    /**
     * 获取所有栏目权限
     * @return array
     */
    public static function getAllCategoryPermission()
    {
        $getAllSysPermission = self::getAllSysPermission();
        return $getAllSysPermission && isset($getAllSysPermission['cate']) ? $getAllSysPermission['cate'] : [];
    }


    /**
     * 获取所有登录后通用的权限
     * @return array
     */
    public static function getAllLoginPermission()
    {
        $getAllSysPermission = self::getAllSysPermission();
        return $getAllSysPermission && isset($getAllSysPermission['login']) ? $getAllSysPermission['login'] : [];
    }

    /**
     * 获取所有模块内通用的权限
     * @return array
     */
    public static function getAllModulePermission()
    {
        $getAllSysPermission = self::getAllSysPermission();
        return $getAllSysPermission && isset($getAllSysPermission['module']) ? $getAllSysPermission['module'] : [];
    }

    /**
     * 管理员菜单（系统模块操作）权限验证
     * @return bool
     */
    public static function menuCheck()
    {
        $getLoginUserMenuPermission = self::getLoginUserMenuPermission();
        if (!$getLoginUserMenuPermission) return false;
        // 系统管理员通过
        if (in_array('admin', $getLoginUserMenuPermission)) {
            return true;
        }
        $permission = Route::currentRouteName();
        if (!$permission) {
            return false;
        }
        $getPublic = self::getAllSystemPublicPermission();
        // 验证通用性：公共-无需登录都可访问
        if (in_array($permission, $getPublic['public'])) {
            return true;
        }
        // 验证通用性：登录-登录都可访问
        if (in_array($permission, $getPublic['login'])) {
            return true;
        }
        // 验证通用性：模块通用-登录后模块内可访问
        if (in_array($permission, $getPublic['module'])) {
            return true;
        }
        // 验证菜单功能权限
        if (!in_array($permission, $getLoginUserMenuPermission)) {
            return false;
        }
        return true;
    }

    /**
     * 管理员栏目（栏目下数据操作）权限验证
     * @return bool
     */
    public static function cateCheck(InfoCategory $info_category)
    {
        if (!$info_category) {
            return false;
        }
        $getLoginUserCategoryPermission = self::getLoginUserCategoryPermission();
        if (!$getLoginUserCategoryPermission) return false;
        // 系统管理员通过
        if (in_array('admin', $getLoginUserCategoryPermission)) {
            return true;
        }
        $permission = self::getCategoryPermissionName($info_category->id);
        if (!$permission || !in_array($permission, $getLoginUserCategoryPermission)) {
            return false;
        }
        return true;
    }

    /**
     * 根据模块（控制器）获取模块名称
     * @param string $controller // 控制器
     * @return string
     */
    public static function getModuleNameByController($controller = "")
    {
        if (!$controller) return '';
        $getPermission = Permission::where([['type', 1], ['controller', $controller]])->first();
        if (!$getPermission) return '';
        return $getPermission['name'];
    }

    /**
     * 根据权限获取权限名称（即操作行为）
     * @param string $priv // 权限即路由别名
     * @return string
     */
    public static function getPermissionNameByPriv($priv = "")
    {
        if (!$priv) return '';
        $getPermission = Permission::where([['type', 2], ['priv', $priv]])->first();
        if (!$getPermission) return '';
        return $getPermission['name'];
    }


    /**
     * 批量添加权限数据
     * @return bool // 是否更新
     */
    public static function patchStore()
    {
        $is_update = false;
        $getAllCurrent = Permission::all();
        // 模块数据处理：type=1 && controller
        $getCurrentController = collect($getAllCurrent)->filter(function ($item) {
            return $item->type == 1;
        })->values()->all();
        $allRouteController = RouteService::getPermissionRouteControllerList();
        $insert_controller_data = [];
        collect($allRouteController)->each(function ($item) use ($getCurrentController, &$insert_controller_data) {
            $is_exist = collect($getCurrentController)->contains('controller', $item['controller']);
            if (!$is_exist) {
                array_push($insert_controller_data, [
                    'type' => 1,
                    'controller' => $item['controller'],
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now()
                ]);
            }
        });
        if (!empty($insert_controller_data)) {
            DB::table('permission')->insert($insert_controller_data);
            $is_update = true;
        }

        // 获取模块集合
        $getTmpCurrentController = Permission::where('type', 1)->select(['id', 'controller'])->get();
        $getParentIdByController = function ($controller = "") use (&$getTmpCurrentController) {
            $parent_id = 0;
            collect($getTmpCurrentController)->each(function ($item) use ($controller, &$parent_id) {
                if ($item->controller == $controller) {
                    $parent_id = $item->id;
                    return false;
                }
            });
            return $parent_id;
        };

        // 权限数据处理：type=2 && priv
        $getCurrentPermission = collect($getAllCurrent)->filter(function ($item) {
            return $item->type == 2;
        })->values()->all();
        $allRoutePermission = RouteService::getPermissionRouteList();
        $insert_permission_data = [];
        collect($allRoutePermission)->each(function ($item) use ($getCurrentPermission, &$insert_permission_data, $getParentIdByController) {
            $is_exist = collect($getCurrentPermission)->contains('priv', $item['name']);
            if (!$is_exist) {
                array_push($insert_permission_data, [
                    'type' => 2,
                    'parent_id' => $getParentIdByController($item['controller']),
                    'priv' => $item['name'],
                    'uri' => $item['uri'],
                    'request_methods' => $item['methods'],
                    'controller' => $item['controller'],
                    'controller_method' => $item['controller_method'],
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now()
                ]);
            }
        });
        if (!empty($insert_permission_data)) {
            DB::table('permission')->insert($insert_permission_data);
            $is_update = true;
        }
        return $is_update;
    }


}
